home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
VISUALBA
/
BOZOL2.ZIP
/
PREP.BAS
< prev
next >
Wrap
BASIC Source File
|
1994-02-08
|
6KB
|
136 lines
SUB PREP (Prg$)
' Prep can do a lot of things depending on how complicated you want your
' language to be. EXEC simply parses the line apart and looks for three
' things which it can handle. It looks for statements (PRINT, INPUT), it
' looks for functions (UCASE, VAL) and it looks for arguments (numbers or
' variables like A,B,GRANNY,USERNAME). If this is all we need for our
' language then PREP is not necessary, PREP is required to do at least 2
' very necessary things in order to make our language truly viable. First,
' EXEC "parses" what is passed to it by looking for spaces, commas and
' semicolons (these are interchangeable). EXEC does not understand the
' concept of QUOTED STRINGS since quoted strings may contain spaces and
' punctuation that would confuse the parsing technique. Of course, we
' could teach EXEC to look for begin and end quotes and not parse or
' attempt to interpret what is between them, and to simply push the
' entire quoted string onto the argument stack, but this would really
' slow things down. It is better to deal with quoted strings all at once
' beforehand. Of course, it would be even better to PREP the WHOLE PROGRAM
' before it is executed, and this would give us an added opportunity to
' strip REMarks, pre-establish the positions of labels, and pack out blank
' lines, but this would start to make this source code harder and harder
' to understand, and we're trying to make this as easy as we can.
' Remove all quoted strings and make temporary variables out of them.
X%=65
DO
a%=INSTR(PRG$,CHR$(34))
IF a% THEN
VALUE$=MID$(PRG$, a%)
b%=INSTR(2,VALUE$,CHR$(34))
IF b% THEN VALUE$=LEFT$(VALUE$,b%)
REPLACE VALUE$ WITH CHR$(1,X%) IN PRG$
ARRAY SCAN VAR$(1), COLLATE UCASE, =CHR$(1,X%), TO i%
IF i% THEN
VALUE$(i%)=REMOVE$(VALUE$,CHR$(34))
ELSE
INCR NextVar%
VALUE$(NextVar%)=REMOVE$(VALUE$,CHR$(34))
VAR$(NextVar%)=CHR$(1,X%)
END IF
ELSE
EXIT LOOP
END IF
INCR X%
LOOP
' Secondly, we have to deal with the harsh realities of NUMERIC EXPRESSIONS.
' We could certainly work that into EXEC as well, using a technique called
' RECURSIVE DESCENT PARSING, but that, too would start making things a bit
' hideous.
' Being able to handle an line like ...
' PRINT B*20/C+(INT(D/100))
' ... where a statement is followed by an expression which includes
' literal numbers and variables and functions (like INT) would require a
' much more complex parsing algorithm than we are introducing here.
' Another way to deal with expressions is to force any arithmetic to
' be performed in special arithmetic functions, like ...
'
' PRINT ADD(DIV(MUL(B,20),C),INT(DIV(D,100))
'
' with the stack-parsing technique we are using for language processing
' this type of expression would be much much much easier to implement, BUT
' it starts to make our language seem pretty silly, so what we are going to
' do is this: By pushing arithmetic symbols onto the argument stack along
' with the rest of the arguments, a variable-free, statement-free expression
' can be built whenever the stack is popped clean by the CALC function.
' in other words, the above expression would wind up looking like this:
'
' PRINT CALC B*20/C+(INT(CALC D/100))
'
' ... which I would consider more of a fair compromise, and for the burden
' of forcing you to use the CALC command before every arithmetic expression
' you can still use natural arithmetic without having to make your language
' look like FrameWork Fred. (ick!) To accomplish this, we have to make
' sure that arithmetic symbols get parsed and pushed as individuals. In
' order for that to happen, we must ensure that they are separated by a
' parsing character, such as a SPACE.
REPLACE "+" WITH " + " IN PRG$
REPLACE "-" WITH " - " IN PRG$
REPLACE "*" WITH " * " IN PRG$
REPLACE "\" WITH " \ " IN PRG$
REPLACE "/" WITH " / " IN PRG$
REPLACE "^" WITH " ^ " IN PRG$
REPLACE "<" WITH " < " IN PRG$
REPLACE ">" WITH " > " IN PRG$
REPLACE "(" WITH " ( " IN PRG$
REPLACE ")" WITH " ) " IN PRG$
REPLACE "=" WITH " = " IN PRG$
' Now, finally, we will be dealing in a free-form program structure where
' the single string being processed here may contain carriage returns and
' line feeds. In the case of multiple lines, we don't want the whole
' module executed in reverse (which is what stack-parsing does) so we will
' remove all carriage returns and line feeds, and we'll be flipping the
' lines, so the last lines come first and the first come last. To fully
' understand why we are doing this, you must fully understand stack-parsing.
' In stack parsing, we push every item in a single statement onto a stack,
' processing it as it goes, from last to first. If you have a line which
' read like this:
'
' print mid$ (A$, Y%, 1)
' ^^^^^ ^^^^ ^^^^ ^^^ ^^
' STATEMENT FUNCTION VARIABLE VARIABLE ARGUMENT
' ... the stack-parser start out by pushing the argument 1 as a literal
' number. Then it would evaluate Y% and push it's value as a literal
' number. Then it would evaluate A$ and push it's contents as a literal
' string. Then it would get to the function MID$. It would POP the three
' arguments in order to see what it needs to MID$ with, and then push the
' result as a literal string. Finally, PRINT would see that one single
' item on the stack (the result of MID$) and print it. For more information
' about stack parsing, go back 20 lines and read this again until you get it.
IF INSTR(PRG$,ANY CHR$(13,58)) THEN
' remove all line feeds (PBWrite and other text editors produce them)
' Add a closing carriage return, just in case, and then reverse
' the order of every line of text.
PRG$=REVERSE$(REMOVE$(PRG$,CHR$(10)))
' and remove blank lines
END IF
REPLACE " " WITH " " IN PRG$ ' elimate double spaces
END SUB
FUNCTION REVERSE$(X$)
IF X$="" THEN EXIT FUNCTION
IF INSTR(X$,ANY CHR$(13,58)) = 0 THEN
REVERSE$=X$
EXIT FUNCTION
ELSE
Y$=LEFT$(X$,INSTR(X$,ANY CHR$(13,58))-1)
Z$=MID$(X$,INSTR(X$,ANY CHR$(13,58))+1)
REVERSE$=REVERSE$(Z$)+" " + Y$
END IF
END FUNCTION